package com.klun.concTrueWar.twelve;

import java.util.concurrent.Semaphore;

/**
 *  BoundedBuffer 基于信号量的 有界缓存
 * @param <E>
 */
public class BoundedBuffer<E> {
    private final Semaphore availableItems,availableSpaces;
    private final E[] items;
    private int putPosition = 0,takePosition=0;

    public BoundedBuffer(int capacity) {
        // 设置条数信号量为 0;
        availableItems = new Semaphore(0);
        availableSpaces = new Semaphore(capacity);
        items = (E[]) new Object[capacity];
    }
    public boolean isEmpty(){
        return availableItems.availablePermits() == 0;
    }
    public boolean isFull(){
        return availableSpaces.availablePermits() == 0;
    }
    public void put(E x) throws InterruptedException {
        availableSpaces.acquire();
        doInsert(x);
        availableItems.release();
    }
    public E take() throws InterruptedException {
        availableItems.acquire();
        E item = doExtract();
        availableSpaces.release();
        return item;
    }
    // 和删除形成互斥
    private synchronized void doInsert(E x){
        int i = this.putPosition;
        items[i] = x;
        // 放入的位置是最后一位 则为0 否则为当前位置 数组中形成一个循环放值
        putPosition = (++i == items.length)?0:i;
    }
    // 和插入形成互斥
    private synchronized E doExtract(){
        int i = this.takePosition;
        E x = items[i];
        // 显示的将数组中的元素置空
        items[i] = null;
        // 和普通Position一样 所以遵循先进后出 原则
        takePosition = (++i == items.length)?0:i;
        return x;
    }

}
